<template>
  <div class="my_page_container">
    <q-table
      id="my-xls"
      bordered
      flat
      separator="cell"
      :tableTitle= "tableTitle"
      :columns="columns"
      row-key="id"
      :rows="menuTreeList"
      :pagination="dbPagination"
      :rows-per-page-options="[10,20]"
      v-model:selected="selectedItems"
    >
      <!--  插槽：表格头部左侧    -->
      <!-- <template v-slot:top-left>
        <q-input outlined dense color="base" v-model="filterText" :input-style="{ width: '150px'}">
          <template v-slot:append>
            <q-icon name="search" color="indigo" @click="searchTableAry"/>
          </template>
        </q-input>
      </template> -->

      <!--  插槽：表格头部左侧    -->
      <template v-slot:top-right>
        <div class="q-gutter-sm">
          <q-btn
            dense
            unelevated
            color="primary"
            label="刷新"
            icon="mdi-camera-flip"
            @click="refreshMenu"
          />
          <q-btn
            dense
            unelevated
            color="secondary"
            label="新增"
            icon="mdi-comment-plus"
            @click="addDlgItem(0)"
          />
          <q-btn
            dense
            unelevated
            color="amber"
            label="导入"
            icon="mdi-file-import"
          />
          <q-btn
            dense
            unelevated
            color="pink"
            label="导出"
            icon="mdi-database-export"
          />
        </div>
      </template>

      <template v-slot:header="props">
        <q-tr>
          <q-th
            v-for="col in props.cols"
            :key="col.name"
            :props="props">{{ col.label }}
          </q-th>
        </q-tr>
      </template>

      <template #body="props">
        <q-tr :props="props">
          <q-td key="id" align="center">
            <q-btn
              dense
              round
              flat
              :icon="props.expand ? 'mdi-minus' : 'mdi-plus'"
              @click="props.expand = !props.expand"
            />
          </q-td>
          <q-td key="label" align="center"><div>{{ props.row.label }}</div></q-td>
          <q-td key="icon" align="center">
            <q-icon :name="props.row.icon" size="sm" color="t-grey" />
          </q-td>
          <q-td key="menuType" align="center">
            {{findCatalogLabel(menuTypeList, props.row.menuType)}}</q-td>
          <q-td key="sortCode" align="center">{{ props.row.sortCode }}</q-td>
          <q-td key="privilege" align="center">{{ props.row.privilege }}</q-td>
          <q-td key="url" align="center">
            {{ props.row.url }}
          </q-td>
          <q-td key="component" align="center">{{ props.row.component }}</q-td>
          <q-td key="operation" align="center">
            <q-btn
              v-if="findCatalogLabel(menuTypeList, props.row.menuType) === '目录'"
              flat
              round
              dense
              color="primary"
              icon="add"
              @click="addDlgItem(props.row.id)"
            >
              <q-tooltip>添加</q-tooltip>
            </q-btn>
            <q-btn
              flat
              round
              dense
              color="primary"
              icon="edit"
              @click.stop="editDlgItem(props.row.id)"
            >
              <q-tooltip>编辑</q-tooltip>
            </q-btn>
            <q-btn
              flat
              round
              dense
              color="negative"
              icon="mdi-delete-empty"
              @click="deleteDlgItem(props.row.id)"
            >
              <q-tooltip>删除</q-tooltip>
            </q-btn>
          </q-td>
        </q-tr>

        <q-tr
          v-show="props.expand"
          :props="props"
          v-for="item in props.row.children"
          :key="item.id"
        >
          <q-td align="center">
          </q-td>
          <q-td key="label" align="center"><div>{{ item.label }}</div></q-td>
          <q-td key="icon" align="center">
            <q-icon :name="item.icon" size="sm" color="t-grey" />
          </q-td>
          <q-td key="menuType" align="center">
            {{findCatalogLabel(menuTypeList, item.menuType)}}</q-td>
          <q-td key="sortCode" align="center">{{ item.sortCode }}</q-td>
          <q-td key="privilege" align="center">{{ props.row.privilege }}</q-td>
          <q-td key="url" align="center">
            {{ item.url }}
          </q-td>
          <q-td key="component" align="center">{{ item.component }}</q-td>
          <q-td key="operation" align="center">
            <q-btn
              flat
              round
              dense
              color="primary"
              icon="edit"
              @click.stop="editDlgItem(item.id)"
            >
              <q-tooltip>编辑</q-tooltip>
            </q-btn>
            <q-btn
              flat
              round
              dense
              color="negative"
              icon="mdi-delete-empty"
              @click="deleteDlgItem(item.id)"
            >
              <q-tooltip>删除</q-tooltip>
            </q-btn>
          </q-td>
        </q-tr>
      </template>

      <!--   底部插槽     -->
      <template v-slot:bottom>
        <AmyPagination :page-msg="dbPagination" @update="refreshTableAry"/>
      </template>
    </q-table>
    <MenuDlg
      ref="myAddDlgRef"
      :item-data="getActiveItem()"
      :menu-type-arr="menuTypeList"
      :menu-arr= "menuList"
      :icon-arr="iconList"
      @cancel-menu-item="cancelAddDlg"
      @submit-menu-item="submitAddDlg"
    />
    <AmyDeleteDlg
      ref="myDelDlgRef"
      :selected-index="deletedIndex"
      @btnSubmit="submitDelDlg"
    />
  </div>
</template>

<script lang="ts">
import { defineAsyncComponent, defineComponent, onMounted, ref, reactive, watch, onUnmounted } from 'vue';
import { useSysCatalogTbl } from '../../../hook/useSysCatalogTbl';
import { sysCatalogType, sysBaseVOAPI, sysBaseUrlAPI } from '../../../util/SysBaseConst';
import api from 'axios';
import { useMessageNotify } from 'src/hook/common/useMessageNotify';
import BaseItem from 'pages/BaseItem.vue';
import { EStatusType, ItemType } from 'src/hook/common/useCommonVisitType';
import useCommonVisitDatabase from 'src/hook/common/useCommonVisitDatabase';
import { useCatalogTool } from 'src/hook/common/useCatalogTool';

import { MenuItem, MenuTreeVOItem } from './MenuModel';
import { useCommonStore } from 'stores/commonStore';

const AmyDeleteDlg = defineAsyncComponent(() => import('components/basic/AmyDeleteDlg.vue'));
const AmyDate = defineAsyncComponent(() => import('components/basic/AmyDate.vue'));
const AmyPagination = defineAsyncComponent(() => import('components/grid/AmyPagination.vue'));
const MenuDlg = defineAsyncComponent(() => import('./MenuDlg.vue'));
export type MenuAddDlgInstance = InstanceType<typeof MenuDlg>;
export type DeleteDlgInstance = InstanceType<typeof AmyDeleteDlg>;


export default defineComponent({
  name: 'MenuIndex',
  extends: BaseItem,
  components: {
    AmyDeleteDlg,
    MenuDlg,
    AmyPagination
  },

  setup (props, context) {
    //*********************************************************************************************
    //      store
    //*********************************************************************************************
    //store，刷新菜单
    const store = useCommonStore();

    //*********************************************************************************************
    //      消息通知
    //*********************************************************************************************
    //消息通知
    const {
      showSuccessMessage,
      showMessage
    } = useMessageNotify();

    //*********************************************************************************************
    //      模糊检索功能
    //*********************************************************************************************
    let menuTreeList = ref<MenuTreeVOItem[]>([]);

    //list生成树
    const generateMenuTree = (arr: MenuItem[]): MenuTreeVOItem[] => {
      let list = [] as MenuTreeVOItem[];

      //找出菜单目录
      let menuList = arr.filter((item) => (item.pid === 0));
      let subMenuList = arr.filter((item) => (item.pid > 0));
      menuList.forEach((item) => {
        let a = {
          id: item.id,
          pid: item.pid,
          label: item.label,
          value: item.value,
          icon: item.icon,
          url: item.url,
          component: item.component,
          menuType: item.menuType,
          privilege: item.privilege,
          sortCode: item.sortCode,
          operation: item.operation,
          children: [] as MenuTreeVOItem[]
        };

        //找到子菜单
        subMenuList.forEach((el) => {
          if (el.pid === item.id) {
            a.children.push({
              id: el.id,
              pid: el.pid,
              label: el.label,
              value: el.value,
              icon: el.icon,
              url: el.url,
              component: el.component,
              menuType: el.menuType,
              privilege: el.privilege,
              sortCode: el.sortCode,
              operation: el.operation,
              children: [] as MenuTreeVOItem[]
            });
          }
        });

        //插入数组
        list.push(a);
      });

      return list;
    }

    //*********************************************************************************************
    //      读取表格数据
    //*********************************************************************************************
    //检索响应数据
    const state = reactive({
      itemData: {
        id: 0,
        pid: 0,
        label: '',
        value: '',
        icon: '',
        url: '',
        component: '',
        menuType: 0,
        privilege: 0,
        sortCode: '',
        operation: '',
        createTime: '',
        createUserId: 0,
        updateTime: '',
        updateUserId: 0
      }
    });

    //查询数据库
    const fetchApi = () => {
      return api.post(sysBaseUrlAPI.SYS_MENU_API_PAGE, {
        pageNum: dbPagination.value.pageNum,
        pageSize: dbPagination.value.pageSize
      });
    };

    //删除记录
    const deleteApi = (item: ItemType) => {
      return api.post(sysBaseUrlAPI.SYS_MENU_API_DELETE, { id: item.id });
    };

    //增加记录
    const confirmAddApi = (item: ItemType) => {
      return api.post(sysBaseUrlAPI.SYS_MENU_API_ADD, {
        id: 0,
        pid: item.pid,
        label: item.label,
        value: item.value,
        icon: item.icon,
        url: item.url,
        component: item.component,
        menuType: item.menuType,
        privilege: item.privilege,
        sortCode: item.sortCode,
        operation: item.operation,
        createTime: '',
        createUserId: 0,
        updateTime: '',
        updateUserId: 0
      });
    };

    //修改记录
    const confirmEditApi = (item: ItemType) => {
      return api.post(sysBaseUrlAPI.SYS_MENU_API_UPDATE, {
        id: item.id,
        pid: item.pid,
        label: item.label,
        value: item.value,
        icon: item.icon,
        url: item.url,
        component: item.component,
        menuType: item.menuType,
        privilege: item.privilege,
        sortCode: item.sortCode,
        operation: item.operation,
        createTime: '',
        createUserId: 0,
        updateTime: '',
        updateUserId: 0
      });
    };

    const {
      dbList,
      dbFilterList,
      dbPagination,
      dbCurrentIndex,
      dbStatus,
      getActiveItem,
      filterList,
      loadList,
      addItem,
      editItem,
      deleteItem,
      cancelItem,
      confirmApi
    } = useCommonVisitDatabase(state.itemData, fetchApi, confirmAddApi, confirmEditApi, deleteApi);

    //*********************************************************************************************
    //      目录模块
    //*********************************************************************************************
    const {
      findCatalogLabel,
      findCatalogId
    } = useCatalogTool();

    const {
      menuTypeList,
      menuList,
      iconList,
      getCatalog,
      removeCatalog
    } = useSysCatalogTbl();

    //*********************************************************************************************
    //      表格
    //*********************************************************************************************
    const columns = [
      {
        name: 'id',
        required: true,
        label: '',
        align: 'center',
        field: (row:any) => (row.id)
      },
      { name: 'label', align: 'center', label: '菜单名称', field: 'label' },
      { name: 'icon', align: 'center', label: '菜单图标', field: 'icon' },
      { name: 'menuType', align: 'center', label: '菜单类型', field: 'menuType' },
      { name: 'sortCode', align: 'center', label: '菜单序码', field: 'sortCode' },
      { name: 'privilege', align: 'center', label: '范围', field: 'privilege' },
      { name: 'url', align: 'center', label: '路由地址', field: 'url' },
      { name: 'component', align: 'center', label: '组件名称', field: 'component' },
      { name: 'operation', align: 'center', label: '操作', field: 'operation' }
    ];

    let tableTitle = ref('用户数据');
    let selectedItems = ref([]);
    let filterText = ref('');
    let myDelDlgRef = ref<DeleteDlgInstance | null>(null);
    let myAddDlgRef = ref<MenuAddDlgInstance | null>(null);
    let deletedIndex = ref(0);

    //检索显示
    const searchTableAry = () => {
      filterList(filterText.value);
    }

    //刷新菜单栏
    const refreshMenu = () => {
      store.setMenuStatus(true);
      console.log('refresh:' + store.menuRefresh);
    }

    //添加用户
    const addDlgItem = (pid: number) => {
      if (myAddDlgRef.value) {
        addItem();
        (dbList.value[0] as MenuItem).pid = pid;
        myAddDlgRef.value.show('新建菜单信息');
      }
    }

    //编辑用户
    const editDlgItem = (id: number) => {
      if (myAddDlgRef.value) {
        let index = dbList.value.findIndex((item: any) => item.id === id);
        if (index > -1) {
          editItem(index);
          myAddDlgRef.value.show('编辑菜单信息');
        }
      }
    }

    //删除用户
    const deleteDlgItem = (id: number) => {
      if (myDelDlgRef.value) {
        let index = dbList.value.findIndex((item: any) => item.id === id);
        if (index > -1) {
          deletedIndex.value = index;
          myDelDlgRef.value.show('菜单信息');
        }
      }
    }

    //更新分页组件
    const refreshTableAry = (pageNum: number) => {
      dbPagination.value.pageNum = pageNum;
      loadList();
    }

    //格式
    let classes = ref('bg-grey-6');
    let dense = ref(false);
    let dark = ref(false);

    //*********************************************************************************************
    //      增加、修改模块
    //*********************************************************************************************
    //取消添加
    const cancelAddDlg = () => {
      //判断是增加还是修改
      if (dbStatus.value === EStatusType.ADD_TYPE) {
        cancelItem(0);
      }
    }

    //新建提交
    const submitAddDlg = (item: MenuItem) => {
      confirmApi(item);
      loadList();
    }

    //*********************************************************************************************
    //      删除确认模块
    //*********************************************************************************************
    //提交确认对话框
    const submitDelDlg = (index: number) => {
      deleteItem(index);
    }

    //*********************************************************************************************
    //      启动模块
    //*********************************************************************************************
    //初始化
    const init = () => {
      //修改一页显示数量
      dbPagination.value.pageSize = 50;

      //表格数据,无条件查询
      loadList();

      //目录
      getCatalog(sysCatalogType.MENU_TYPE_CODE);
      getCatalog(sysCatalogType.MENU_CODE);
      getCatalog(sysCatalogType.ICON_CODE);
    }

    //监视检索框
    watch(filterText, () => {
      searchTableAry();
    });

    //监视数据源
    watch(() => dbList, () => {
      menuTreeList.value = generateMenuTree(dbList.value as MenuItem[]);
    }, { deep: true });

    //挂载数据
    onMounted(() => {
      init();
    });

    //销毁数据
    onUnmounted(() => {
      removeCatalog(sysCatalogType.MENU_TYPE_CODE);
      removeCatalog(sysCatalogType.MENU_CODE);
      removeCatalog(sysCatalogType.ICON_CODE);
    });

    return {
      menuTreeList,

      findCatalogLabel,
      findCatalogId,

      menuTypeList,
      menuList,
      iconList,

      columns,
      tableTitle,
      selectedItems,
      filterText,
      deletedIndex,
      myDelDlgRef,
      myAddDlgRef,
      searchTableAry,
      addDlgItem,
      editDlgItem,
      deleteDlgItem,
      refreshTableAry,
      refreshMenu,

      classes,
      dense,
      dark,

      dbList,
      dbFilterList,
      dbPagination,
      dbCurrentIndex,
      getActiveItem,
      loadList,
      addItem,
      editItem,
      deleteItem,
      cancelItem,
      confirmApi,

      cancelAddDlg,
      submitAddDlg,
      submitDelDlg,

      sysCatalogType
    }
  }
})
</script>

<style lang="scss">
.my_input {
  width: 150px;
}

</style>
